package com.credithc.signature.common.service;

import com.credithc.baseserv.pageHelper.PageInfo;
import com.credithc.signature.common.constant.CoreConstant;
import com.credithc.signature.common.constant.ManagerConstant;
import com.credithc.signature.common.mapper.*;
import com.credithc.signature.common.po.Dictionary;
import com.credithc.signature.common.po.*;
import com.credithc.signature.common.ro.manager.RequestLogRo;
import com.credithc.signature.common.ro.sign.SealCertInfoRo;
import com.credithc.signature.common.to.CFCASignTO;
import com.credithc.signature.common.utils.*;
import com.credithc.signature.common.vo.manager.DictionaryVo;
import com.credithc.signature.common.vo.manager.RequestLogVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.text.SimpleDateFormat;
import java.util.*;

@Service
@Slf4j
public class SignatureLogService {

    @Value("${file.download.url:null}")
    String downloadUrl;

    @Value("${S3.file.download.url:null}")
    String downloadUrlS3;

    @Autowired
    private SignatureLogMapper signatureLogMapper;

    @Autowired
    CertInfoService certInfoService;

    @Autowired
    private SignatureLogExtMapper signatureLogExtMapper;

    @Autowired
    ChannelMapper channelMapper;

    @Autowired
    TemplateMapper templateMapper;

    @Autowired
    TemplateService templateService;

    @Autowired
    private CertInfoMapper certInfoMapper;

    @Autowired
    private ProductSignMapper productSignMapper;

    @Autowired
    private DictionaryService dictionaryService;

    @Autowired
    CFCASignService cfcaSignService;

    @Autowired
    ChannelService channelService;

    //*-*!
    public int updateByReqSNSelective(SignatureLog signatureLog) {
        signatureLog.setUpdateTime(new Date());
        Example example = new Example(SignatureLog.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("requestSn", signatureLog.getRequestSn());
        criteria.andLessThanOrEqualTo("createTime", DateUtil.getNextDate(1));
        criteria.andGreaterThanOrEqualTo("createTime", DateUtil.getBeforeDate(2));
        return signatureLogMapper.updateByExampleSelective(signatureLog, example);
    }


    public void updateResult(String result, String requestSN) {
        SignatureLog signatureLog = new SignatureLog();
        signatureLog.setRequestSn(requestSN);
        signatureLog.setSignResult(result);
        signatureLog.setUpdateTime(new Date());
        // 设置制私章耗时时间（秒）
        setMakeSealTime(signatureLog);
        Example example = new Example(SignatureLog.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("requestSn", signatureLog.getRequestSn());
        signatureLogMapper.updateByExampleSelective(signatureLog, example);
    }

    private void setMakeSealTime(SignatureLog signatureLog) {
        Example e = new Example(SignatureLog.class);
        Example.Criteria c = e.createCriteria();
        c.andEqualTo("requestSn", signatureLog.getRequestSn());
        SignatureLog select = signatureLogMapper.selectOneByExample(e);
        Long lastSeconds = DateUtil.betweenNowSecond(select.getCreateTime());
        signatureLog.setLastTime(lastSeconds.intValue());
    }

    public List<SignatureLog> selectByExampleAndRowBounds(Object example, RowBounds rowBounds) {
        return signatureLogMapper.selectByExampleAndRowBounds(example, rowBounds);
    }

    public int selectCountByExample(Object example) {
        return signatureLogMapper.selectCountByExample(example);
    }

    /**
     * 更新签章数量
     *
     * @param requetSN
     * @param personSealNum
     * @param officalSealNum
     */
    public void updateSealNum(String requetSN, Integer personSealNum, Integer officalSealNum) {
        SignatureLog signatureLog = new SignatureLog();
        signatureLog.setRequestSn(requetSN);
        if (personSealNum > 0) {
            signatureLog.setPersonalSealNum(personSealNum);
        }
        signatureLog.setPersonalSealNum(personSealNum);
        if (officalSealNum > 0) {
            signatureLog.setOfficialSealNum(officalSealNum);
        }
        // 设置处理中
        signatureLog.setSignStatus(1);
        this.updateByReqSNSelective(signatureLog);
    }

    /**
     * 插入私章信息
     *
     * @param cfcaSignTO
     * @param requestSn
     */
    public void insertPersonalSeal(CFCASignTO cfcaSignTO, String requestSn) {
        // 如果存在则不需要插入
        SealApplyInfoDTO sealInfoDTO = certInfoService.getSealInfoByCode(cfcaSignTO.getSealCode());
        if (sealInfoDTO != null) {
            return;
        }
        Date current = new Date(System.currentTimeMillis());
        try {
            SealCertInfoRo certInfoRo = cfcaSignService.querySealApplyInfo(requestSn, cfcaSignTO.getUserName(), cfcaSignTO.getIdTypeCode(), cfcaSignTO.getUserIdNo());
            if (certInfoRo != null) {
                String certNotBefore = certInfoRo.getCertNotBefore();
                String certNotAfter = certInfoRo.getCertNotAfter();
                certNotBefore = certNotBefore.substring(0, certNotBefore.indexOf("."));
                certNotAfter = certNotAfter.substring(0, certNotAfter.indexOf("."));
                Date notBefore = DateUtil.getDateFromStr(certNotBefore);
                Date notAfter = DateUtil.getDateFromStr(certNotAfter);
                String certSN = certInfoRo.getCertSN();
                String certDN = certInfoRo.getCertDN();
                SealApplyInfoDTO sealApplyInfo = new SealApplyInfoDTO(UUIDUtil.getUUID(), 1, CoreConstant.ORG_CODE, cfcaSignTO.getSealCode(), cfcaSignTO.getSealPassword(),
                        cfcaSignTO.getUserName(), cfcaSignTO.getIdTypeCode(), cfcaSignTO.getUserIdNo(), 0, certDN, certSN, 5, 1,
                        notBefore, notAfter, current, current);
                certInfoMapper.insertSelective(sealApplyInfo);
            }
        } catch (Exception e) {
            log.error(LogUtil.outPut(requestSn, "插入私章信息失败,错误信息:" + e.getMessage()));
        }
    }

    //----------------------------------------主方法----------------------------------------

    /**
     * 查询全部已完成队列数据
     *
     * @param requestLogRo
     * @return
     */
    public PageInfo<RequestLogVo> queryAll(RequestLogRo requestLogRo) {
        if (requestLogRo.getChannelNos() != null) {
            long startTime = System.currentTimeMillis();
            log.info("查询所有签章记录channelNos=" + requestLogRo.getChannelNos());
            PageUtils.setPageNo(requestLogRo);
            List<SignatureLog> logPos = signatureLogMapper.querySignatureLogList(requestLogRo);
            int count = signatureLogMapper.querySignatureLogListCount(requestLogRo);
            List<RequestLogVo> vos = buildPos(logPos);
            log.info("<== requestLog 查询耗时 : {}", (System.currentTimeMillis() - startTime));
            return new PageInfo<>(vos, count, requestLogRo.getPageNo(), requestLogRo.getPageSize());
        } else {
            return new PageInfo<>(null, 0, requestLogRo.getPageNo(), requestLogRo.getPageSize());
        }
    }

    /**
     * 查询单条
     *
     * @param id
     * @return
     */
    public RequestLogVo queryOne(Long id, String date) {
        Date startTime = DateUtil.getTodayStartTime(date);
        Date lastTime = DateUtil.getTodayLastTime(date);
        Example example = new Example(SignatureLog.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andBetween("createTime", startTime, lastTime);
        criteria.andEqualTo("id", id);
        SignatureLog SignatureLog = signatureLogMapper.selectOneByExample(example);
        RequestLogVo logVo = new RequestLogVo();
        return convertPotoVo(SignatureLog, logVo, true);
    }

    /**
     * 查看合同
     *
     * @param contractUri
     * @param channelNo
     * @return
     */
    public RequestLogVo lookContract(String contractUri, String channelNo) {
        RequestLogVo requestLogVo = new RequestLogVo();
        // 判断签章供应商
        Example pse = new Example(ProductSign.class);
        Example.Criteria psec = pse.createCriteria();
        psec.andEqualTo("productCode", channelNo);
        List<ProductSign> productSigns = productSignMapper.selectByExample(pse);
        if (productSigns != null) {
            Map<String, Integer> map = new HashMap();
            for (ProductSign p : productSigns) {
                map.put(p.getMethodName(), p.getPercentage());
            }
            Integer fddSignature = map.get("fddSignature");
            if (fddSignature != null && fddSignature == 100) {
                requestLogVo.setContractUri(downloadUrlS3 + contractUri);
            } else {
                requestLogVo.setContractUri(downloadUrl + contractUri);
            }
        } else {
            requestLogVo.setContractUri(downloadUrl + contractUri);
        }
        return requestLogVo;
    }

    /**
     * 查询签章状态
     *
     * @return
     */
    public List<DictionaryVo> querySignStatus() {
        List<Dictionary> dictionaryPos = dictionaryService.selectByType(ManagerConstant.SIGN_STATUS);
        List<DictionaryVo> list = new ArrayList<>();
        dictionaryPos.forEach(po -> {
            DictionaryVo vo = new DictionaryVo();
            BeanUtils.copyProperties(po, vo);
            list.add(vo);
        });
        return list;
    }

    //----------------------------------------工具方法----------------------------------------

    /**
     * 封装Vo类
     *
     * @param logPos
     * @return
     */
    public List<RequestLogVo> buildPos(List<SignatureLog> logPos) {
        List<RequestLogVo> vos = new ArrayList<>();
        logPos.forEach(po -> {
            RequestLogVo logVo = new RequestLogVo();
            vos.add(convertPotoVo(po, logVo, false));
        });
        return vos;
    }


    private RequestLogVo convertPotoVo(SignatureLog signatureLog, RequestLogVo requestLogVo, boolean lookRequestData) {
        BeanUtils.copyProperties(signatureLog, requestLogVo);
        //渠道名称
        if (StringUtils.isNotEmpty(signatureLog.getChannelNo())) {
            Channel channel = channelService.selectCacheByChannelNo(signatureLog.getChannelNo());
            if (channel != null) {
                requestLogVo.setChannelName(channel.getChannelName());
            }
        }
        //模板名称
        if (StringUtils.isNotEmpty(signatureLog.getTemplateNo())) {
            Template template = templateService.selectCacheByTemplateNo(signatureLog.getTemplateNo());
            if (Objects.nonNull(template)) {
                requestLogVo.setTemplateName(template.getTemplateName());
                //签章类型
                Integer sealType = template.getSealType();
                String value = dictionaryService.selectOneByCache(ManagerConstant.SEAL_TYPE, sealType.toString());
                requestLogVo.setSealType(value);
            }
        }
        //是否签章
        if (signatureLog.getIsSeal() != null) {
            int code = !signatureLog.getIsSeal() ? 0 : 1;
            String name = dictionaryService.selectOneByCache(ManagerConstant.SIGN_TYPE, String.valueOf(code));
            requestLogVo.setIsSeal(name);
        }
        //判断三方
        if (signatureLog.getThirdPartyChannel() != null) {
            if (signatureLog.getThirdPartyChannel() == 1) {
                requestLogVo.setThirdPartyChannel("懒猫");
            } else {
                requestLogVo.setThirdPartyChannel("中金");
            }
        }
        //处理状态
        if (signatureLog.getSignStatus() != null) {
            String name = dictionaryService.selectOneByCache(ManagerConstant.SIGN_STATUS, signatureLog.getSignStatus().toString());
            requestLogVo.setSignStatusName(name);
        }
        //回调状态
        if (StringUtils.isNotEmpty(requestLogVo.getSuccessCallCode())) {
            String name = dictionaryService.selectOneByCache(ManagerConstant.CALL_STATUS, signatureLog.getSuccessCallCode());
            requestLogVo.setSuccessCallCode(name);
        }
        //耗时时间(秒)
        if (requestLogVo.getCreateTime() != null && requestLogVo.getUpdateTime() != null) {
            long timeDifference = ManagerBeanUtil.timeDifference(requestLogVo.getCreateTime(), requestLogVo.getUpdateTime());
            requestLogVo.setDifferenceTime(timeDifference);
        }
        //查询扩展表
        if (lookRequestData) {
            Long refId = signatureLog.getRefId();
            Example example = new Example(SignatureLogExt.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("id", refId);
            Date createTime = signatureLog.getCreateTime();
            String defaultAppointDateStr = DateUtil.getDefaultAppointDateStr(createTime);
            criteria.andBetween("createTime", DateUtil.getTodayStartTime(defaultAppointDateStr), DateUtil.getTodayLastTime(defaultAppointDateStr));
            SignatureLogExt logExtPo = signatureLogExtMapper.selectOneByExample(example);
            requestLogVo.setRequestData(logExtPo.getRequestData());
        }
        //过滤signResult特殊字符，防止页面数据不显示
        String signResult = requestLogVo.getSignResult();
        signResult = MessageFilterUtil.filter(signResult);
        requestLogVo.setSignResult(signResult);
        return requestLogVo;
    }


    public Integer queryDayCount() {
        Example example = new Example(RequestLog.class);
        Example.Criteria criteria = example.createCriteria();
        //criteria.andLike("creatTime", new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + "%");
        criteria.andBetween("createTime",DateUtil.getTodayStartTime(new SimpleDateFormat("yyyy-MM-dd").format(new Date())),DateUtil.getTodayLastTime(new SimpleDateFormat("yyyy-MM-dd").format(new Date())));
        int i = 0;
        try {
            i = signatureLogMapper.selectCountByExample(example);
        } catch (Exception e) {
            log.error("数据库错误" + e.getMessage());
        }
        return i;
    }

    public Integer queryDaySuccessCount() {
        Example example = new Example(RequestLog.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("uploadPdfStatus", 1);
        criteria.andBetween("createTime",DateUtil.getTodayStartTime(new SimpleDateFormat("yyyy-MM-dd").format(new Date())),DateUtil.getTodayLastTime(new SimpleDateFormat("yyyy-MM-dd").format(new Date())));
        int i = 0;
        try {
            i = signatureLogMapper.selectCountByExample(example);
        } catch (Exception e) {
            log.error("数据库错误" + e.getMessage());
        }
        return i;
    }
}
